package xyz.noark.codec.output;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.nio.charset.StandardCharsets;

public abstract class CodedOutputStream implements AutoCloseable {
    protected final ByteBuf buffer;
    
    protected CodedOutputStream() {
        this.buffer = Unpooled.buffer();
    }
    
    /**
     * 编码对象方法
     * @param object 要编码的对象
     */
    public abstract void encode(Object object);
    
    public void writeBoolean(boolean value) {
        buffer.writeBoolean(value);
    }
    
    public void writeByte(byte value) {
        buffer.writeByte(value);
    }
    
    public void writeChar(char value) {
        buffer.writeChar(value);
    }
    
    public void writeShort(short value) {
        buffer.writeShort(value);
    }
    
    public void writeInt(int value) {
        buffer.writeInt(value);
    }
    
    public void writeLong(long value) {
        buffer.writeLong(value);
    }
    
    public void writeFloat(float value) {
        buffer.writeFloat(value);
    }
    
    public void writeDouble(double value) {
        buffer.writeDouble(value);
    }
    
    public void writeString(String value) {
        if (value == null) {
            buffer.writeInt(-1);
            return;
        }
        byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
        buffer.writeInt(bytes.length);
        buffer.writeBytes(bytes);
    }
    
    public void writeObject(Object value, Class<?> type) {
        if (value == null) {
            buffer.writeInt(-1);
            return;
        }
        
        // 递归序列化对象
        try (CodedOutputStream os = CodedOutputStreamManager.getOutputStream(type)) {
            os.encode(value);
            byte[] bytes = os.toByteArray();
            buffer.writeInt(bytes.length);
            buffer.writeBytes(bytes);
        }
    }
    
    public byte[] toByteArray() {
        byte[] result = new byte[buffer.readableBytes()];
        buffer.readBytes(result);
        return result;
    }
    
    @Override
    public void close() {
        buffer.release();
    }
} 